Modifying Original file (Fig2_ExtFig4_WT_RPM_Organoids_Allografts_Final.R) on GitHub to generate an RMarkdown Notebook

Load RPM Organoids data

RPM_Orgs <- readRDS("../data/05_2025_RPM_Orgs_Only_ExtFig4a-c.rds")

Load CellTagged Organoid Allografts data

RPM_Orgs_Allo <- readRDS("../data/05_2025_RPM_Orgs_Allo_Fig2d.rds")

Load RPM allograft-only data

RPM_Allo <- readRDS("../data/05_2025_RPM_AllograftOnly_Fig2e.rds")

Load RPM allografts as SingleCellExperiment

sce <- readRDS('../data/RPM_Allo_only_sce.rds')

UMAP Plots

Fig 1i

DimPlot(RPM_Orgs_Allo,  group.by='Sample',cols=sample_cols, reduction='umap',
        label=FALSE, label.size=6, shuffle=TRUE, pt.size=0.01) & NoAxes()

FeaturePlot(RPM_Orgs_Allo, features = c("NE_Consensus1"), 
            pt.size=0.2, reduction='umap', order=TRUE) + 
    ggplot2::scale_color_gradientn(colors=rocket(10, direction=-1)) & NoAxes()


FeaturePlot(RPM_Orgs_Allo, features = c("Basal_Consensus1"), 
            pt.size=0.2, reduction='umap',order=TRUE) + 
    ggplot2::scale_color_gradientn(colors=rocket(10, direction=-1)) & NoAxes()

Fig 1j

Violin plots of expression of TFs by Leiden cluster

genes <- c("Ascl1","Neurod1","Pou2f3","Atoh1","Yap1","Trp63")

# Create violin plots with Kruskal-Wallis test
plots <- lapply(genes, function(gene) {
  p <- VlnPlot(RPM_Orgs_Allo,
               features = gene,
               group.by = "leiden_scVI_1.3",
               cols = my_colors,
               alpha = 0.5) +  # smaller dots
    ggpubr::stat_compare_means(method = "kruskal.test", 
                       label = "p.format", 
                       label.x = 2,size = 5) +
    ggtitle("") +
    theme(plot.title = element_text(face = "italic"), legend.position = "none",  # Remove legend
          axis.title.x = element_blank(),axis.title.y = element_text(size = 20),
          axis.text.y = element_text(size = 20), axis.text.x = element_text(size = 14)) +  # Remove x-axis label
    labs(y = "Expression")  # Change y-axis label to "Expression"
  return(p)
})

# Arrange plots
patchwork::wrap_plots(plots, ncol = 6)

UMAP Plots by Sample and Cluster

Extended Data Fig 4a

DimPlot(RPM_Orgs, group.by='Genotype', cols=c("darkorchid4","orange"), reduction='umap',
        label=FALSE, label.size=6, shuffle=TRUE) & NoAxes()


DimPlot(RPM_Orgs, group.by='cluster', cols=colors_figED4a, reduction='umap',
        label=TRUE, label.size=10) & NoAxes()

Extended Data Fig 4c

DimPlot(RPM_Orgs, reduction = "umap", group.by = "Phase",
        shuffle=TRUE, label=FALSE, pt.size=.05, 
        cols=c("indianred3","green3","royalblue4")) + NoAxes()

Ext. Data Fig. 4d

DimPlot(RPM_Orgs_Allo, reduction = "umap", group.by = "Phase",
        shuffle=TRUE, label=FALSE, pt.size=.05, 
        cols=c("indianred3","green3","royalblue4")) + NoAxes()

# Plot barplot for Ext. Data Fig. 4d #
##### What % of cells per phase in each group? ####
x <- table(Idents(RPM_Orgs_Allo),RPM_Orgs_Allo@meta.data$Phase)
proportions <- as.data.frame(100*prop.table(x, margin = 1))

colnames(proportions)<-c("Cluster", "Sample", "Frequency")

# ggbarplot(proportions, x="Sample", y="Frequency", fill = "Sample", group = "Sample", ylab = "Frequency (percent)", xlab="Phase", palette =c("indianred3","green3","royalblue4"))+ theme_bw()+ facet_wrap(facets = "Cluster", scales="free_y", ncol =4)+ theme(axis.text.y = element_text(size=12)) +rotate_x_text(angle = 45)

# Stacked
p<-ggplot(proportions, aes(fill=Sample, y=Frequency, x=Cluster)) +
  geom_bar(position="stack", stat="identity")

p + scale_fill_manual(values=c("indianred3","green3","royalblue4")) + 
    theme_bw() + 
    theme(axis.text.y = element_text(size=20), axis.text.x=element_text(size=20,angle=45, hjust = 1), 
          axis.title.x = element_text(size=20), axis.title.y = element_text(size=20), 
          legend.text = element_text(size=20), legend.title = element_text(size=20)) +
    labs(x=NULL, y="Frequency (%)", fill=NULL)

Fig 1j

DimPlot(RPM_Allo, group.by='leiden_scVI_1.3', cols=my_colors,
        reduction='umap', label=TRUE, label.size=7) & NoAxes() + theme(legend.position="none")

UMAP by Fate

Fig. 1k

pheno_col<-c("brown2","darkorchid4","dodgerblue","#66A61E","orange","turquoise4")

DimPlot(RPM_Allo, group.by=c("Pheno"), cols=pheno_col, shuffle=TRUE, pt.size=0.6)+NoAxes()

Fig 1l

# Fig 2g plots #
FeaturePlot(RPM_Allo, features = c("NE_spearman"), pt.size=0.2, 
            reduction='umap', order=TRUE) + 
    scale_color_viridis(option="rocket",direction=-1) & NoAxes()

Violin plots of Archetypes by leiden cluster

Ext. Data Fig. 4f

VlnPlot(
  RPM_Allo,
  features = c("A_Archetype1","A2_Archetype1","N_Archetype1","P_Archetype1"),
  group.by = "leiden_scVI_1.3",
  cols = my_colors,
  alpha = 0.7,
  ncol = 2
) & 
  theme(
    axis.text.x = element_text(size = 8),                # smaller x-axis labels
    plot.title = element_text(face = "bold", size=0),          # italicize titles
    axis.title.x = element_text(size = 24),              # optional size tweaks
    axis.title.y = element_text(size = 24)
  ) &
  labs(
    y = "Expression",
    x = "Cluster"
  )

Plot Signature Scores by Phenotype

phenotypes <- as.character(unique(RPM_Allo$Pheno))
pheno_pairs_list <- combn(phenotypes, 2, simplify = FALSE)

Define function to plot violin plots by phenotype

plotVlnByPhen <- function(feature, yl=c(-0.1,0.3), focus=NA) {
    if(!is.na(focus)) {
        pheno_pairs_list <- pheno_pairs_list[sapply(pheno_pairs_list, function(x) focus %in% x)]
    }
    
    scater::plotColData(sce, x = "Pheno", y = feature, colour_by = "Pheno") + 
        scale_discrete_manual(aesthetics = c("colour", "fill"), values=pheno_col) +
        theme(axis.title.y = element_text(size = 24), axis.text.y = element_text(size = 16),
              axis.text.x = element_blank(),   # rotate x-axis labels
              plot.title = element_blank(),    # remove plot title
              legend.position = "none"         # remove legend
        ) + labs(x = "",                     # custom x-axis title
                 y = "Signature score"        # custom y-axis title
        ) + ylim(yl[1], yl[2]) + 
        geom_boxplot(fill=pheno_col, alpha=1/5, position = position_dodge(width = .2),
                     size=0.2, color="black", notch=TRUE, notchwidth=0.3, outlier.shape = 2, outlier.colour=NA) #   + 
        # stat_summary(fun = mean,
        #              geom = "point",
        #              shape = 18,
        #              size = 2,
        #              color = "red",
        #              position = position_dodge(width = 0.5)) + 
        # ggpubr::stat_compare_means(method = "wilcox.test", label = "p.signif", size=4, 
        #                            vjust = 0.5,
        #                            hide.ns = TRUE, comparisons = pheno_pairs_list)
}

Fig 1l

NE correlation

plotVlnByPhen("NE_spearman", yl=c(-.75, .8), focus="NE")

Fig 1m

SCLC cell type consensus signature scores * NE cell * Tuft cell * Basal cell

plotVlnByPhen("NE_Consensus1", yl=c(-0.5, 1))

plotVlnByPhen("Tuft_Consensus1", yl=c(-0.1, 0.5))

plotVlnByPhen("Basal_Consensus1", yl=c(-0.1, 1.1))

Fig 1n

TF target gene scores * ASCL1 targets * NEUROD1 targets * ATOH1 targets * POU2F3 targets * YAP1 activity score

plotVlnByPhen("ASCL1_Targets1", yl=c(-0.1,0.6))

plotVlnByPhen("NEUROD1_Targets1", yl=c(-0.1,0.25))

plotVlnByPhen("ATOH1_Targets1", yl=c(-0.1,.3))

plotVlnByPhen("POU2F3_Targets1", yl=c(-0.1, 0.22))

plotVlnByPhen("YAP1_Activity_Score1", yl=c(-0.1, 1))

LS0tCnRpdGxlOiAiV1QgUlBNIE9yZ2Fub2lkcyBBbGxvZ3JhZnRzIE5vdGVib29rIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKZGF0ZTogMjAyNS0wNi0xNgphdXRob3I6ICJBYmJpZSBJcmVsYW5kLCBEYXJyZW4gVHlzb24iCi0tLQoKTW9kaWZ5aW5nIFtPcmlnaW5hbCBmaWxlIChGaWcyX0V4dEZpZzRfV1RfUlBNX09yZ2Fub2lkc19BbGxvZ3JhZnRzX0ZpbmFsLlIpIG9uIEdpdEh1Yl0oaHR0cHM6Ly9naXRodWIuY29tL1RHT2xpdmVyLWxhYi9JcmVsYW5kX0Jhc2FsX1NDTENfMjAyNS9ibG9iL21haW4vUl9Db2RlL0ZpZzJfRXh0RmlnNF9XVF9SUE1fT3JnYW5vaWRzX0FsbG9ncmFmdHNfRmluYWwuUikgdG8gZ2VuZXJhdGUgYW4gUk1hcmtkb3duIE5vdGVib29rCgojIyMgUmVsYXRlZCB0bzoKKiBGaWcgMWktbgoqIEV4dGVuZGVkIERhdGEgRmlnIDRhLWYKCmBgYHtyfQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMoewogICAgbGlicmFyeSh2aXJpZGlzKQogICAgbGlicmFyeShnZ3Bsb3QyKQogICAgbGlicmFyeShzY2F0ZXIpCiAgICBsaWJyYXJ5KFNldXJhdCkKICAgIGxpYnJhcnkoZ2dwdWJyKQogICAgIyBsaWJyYXJ5KHplbGxrb252ZXJ0ZXIpCn0pCmBgYAoKIyMjIyBEZWZpbmUgY29sb3JzIGZvciBmaWd1cmVzCmBgYHtyfQojIERlZmluZSBjb2xvciBzY2hlbWUgYW5kIHBsb3QgVU1BUCBhcyBpbiBGaWcuIDJlICMKbXlfY29sb3JzIDwtIGMoCiAgIiNFNDFBMUMiLCAjIHN0cm9uZyByZWQKICAiIzM3N0VCOCIsICMgbWVkaXVtIGJsdWUKICAiIzREQUY0QSIsICMgZ3JlZW4KICAiIzk4NEVBMyIsICMgcHVycGxlCiAgIiNGRjdGMDAiLCAjIG9yYW5nZQogICIjRkZGRjMzIiwgIyB5ZWxsb3cKICAiI0E2NTYyOCIsICMgYnJvd24KICAiI2U3Mjk4YSIsICMgcGluawogICIjNjY2NjY2IiwgIyBncmV5CiAgImxhdmVuZGVyIiwgIyB0ZWFsCiAgIiNGQzhENjIiLCAjIHNhbG1vbgogICIjOERBMENCIiwgIyBzb2Z0IGJsdWUKICAiI0U3OEFDMyIsICMgc29mdCBwaW5rIChkaWZmZXJlbnQgZnJvbSA4KQogICIjQTZEODU0IiwgIyBsaWdodCBncmVlbiAoYnV0IHllbGxvd2lzaCB0aW50LCBub3QgZ3JlZW4pCiAgIiNGRkQ5MkYiLCAjIGxlbW9uIHllbGxvdwogICIjRTVDNDk0IiwgIyBsaWdodCBicm93bgogICIjQjNCM0IzIiwgIyBsaWdodCBncmV5CiAgIiMxQjlFNzciLCAjIGRlZXAgdGVhbAogICIjRDk1RjAyIiwgIyBkYXJrIG9yYW5nZQogICIjNzU3MEIzIiwgIyBzdHJvbmcgcHVycGxlCiAgInR1cnF1b2lzZSIgICMgb2xpdmUgZ3JlZW4gKE5PVCBzYW1lIGdyZWVuIGFzIGJlZm9yZSkKKQoKY29sb3JzX2ZpZ0VENGEgPC0gYygnZGVlcHNreWJsdWU0JywgJyNGQzhENjInLCcjMmNhMDJjJywgJ2Jyb3duMScsICdwdXJwbGUnLCAnI0EwNTIyRCcsCiAgICAgICAgICAgICAgICAgICAgJ3BpbmsyJywgICcjYTFjMjk5JywgICcjMGFhNmQ4JywgJ2xpZ2h0Ymx1ZScsJ3NhbG1vbjEnLCdsaWdodGdyZWVuJykKCnNhbXBsZV9jb2xzPC1jKCJvcmFuZ2UiLCIjRDhCRkQ4IiwiZGFya29yY2hpZDQiLCAjIGRlZXAgdGVhbAogICAgICAgICAgICAgICAidHVycXVvaXNlIiwgIiMxQjlFNzciICMgZGFyayBvcmFuZ2UKKQoKcGhlbm9fY29sPC1jKCJicm93bjIiLCJkYXJrb3JjaGlkNCIsImRvZGdlcmJsdWUiLCIjNjZBNjFFIiwib3JhbmdlIiwidHVycXVvaXNlNCIpCgpgYGAKCgojIyMgTG9hZCBSUE0gT3JnYW5vaWRzIGRhdGEKYGBge3J9ClJQTV9PcmdzIDwtIHJlYWRSRFMoIi4uL2RhdGEvMDVfMjAyNV9SUE1fT3Jnc19Pbmx5X0V4dEZpZzRhLWMucmRzIikKYGBgCgojIyMgTG9hZCBDZWxsVGFnZ2VkIE9yZ2Fub2lkIEFsbG9ncmFmdHMgZGF0YQpgYGB7cn0KUlBNX09yZ3NfQWxsbyA8LSByZWFkUkRTKCIuLi9kYXRhLzA1XzIwMjVfUlBNX09yZ3NfQWxsb19GaWcyZC5yZHMiKQpgYGAKCiMjIyBMb2FkIFJQTSBhbGxvZ3JhZnQtb25seSBkYXRhCmBgYHtyfQpSUE1fQWxsbyA8LSByZWFkUkRTKCIuLi9kYXRhLzA1XzIwMjVfUlBNX0FsbG9ncmFmdE9ubHlfRmlnMmUucmRzIikKYGBgCgojIyMgTG9hZCBSUE0gYWxsb2dyYWZ0cyBhcyBTaW5nbGVDZWxsRXhwZXJpbWVudApgYGB7cn0Kc2NlIDwtIHJlYWRSRFMoJy4uL2RhdGEvUlBNX0FsbG9fb25seV9zY2UucmRzJykKYGBgCgoKIyMjIFVNQVAgUGxvdHMKIyMjIyAqKkZpZyAxaSoqCmBgYHtyfQpEaW1QbG90KFJQTV9PcmdzX0FsbG8sICBncm91cC5ieT0nU2FtcGxlJyxjb2xzPXNhbXBsZV9jb2xzLCByZWR1Y3Rpb249J3VtYXAnLAogICAgICAgIGxhYmVsPUZBTFNFLCBsYWJlbC5zaXplPTYsIHNodWZmbGU9VFJVRSwgcHQuc2l6ZT0wLjAxKSAmIE5vQXhlcygpCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CkZlYXR1cmVQbG90KFJQTV9PcmdzX0FsbG8sIGZlYXR1cmVzID0gYygiTkVfQ29uc2Vuc3VzMSIpLCAKICAgICAgICAgICAgcHQuc2l6ZT0wLjIsIHJlZHVjdGlvbj0ndW1hcCcsIG9yZGVyPVRSVUUpICsgCiAgICBnZ3Bsb3QyOjpzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzPXJvY2tldCgxMCwgZGlyZWN0aW9uPS0xKSkgJiBOb0F4ZXMoKQoKRmVhdHVyZVBsb3QoUlBNX09yZ3NfQWxsbywgZmVhdHVyZXMgPSBjKCJCYXNhbF9Db25zZW5zdXMxIiksIAogICAgICAgICAgICBwdC5zaXplPTAuMiwgcmVkdWN0aW9uPSd1bWFwJyxvcmRlcj1UUlVFKSArIAogICAgZ2dwbG90Mjo6c2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycz1yb2NrZXQoMTAsIGRpcmVjdGlvbj0tMSkpICYgTm9BeGVzKCkKYGBgCiMjIyMgRmlnIDFqClZpb2xpbiBwbG90cyBvZiBleHByZXNzaW9uIG9mIFRGcyBieSBMZWlkZW4gY2x1c3RlcgpgYGB7ciBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTE1LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnZW5lcyA8LSBjKCJBc2NsMSIsIk5ldXJvZDEiLCJQb3UyZjMiLCJBdG9oMSIsIllhcDEiLCJUcnA2MyIpCgojIENyZWF0ZSB2aW9saW4gcGxvdHMgd2l0aCBLcnVza2FsLVdhbGxpcyB0ZXN0CnBsb3RzIDwtIGxhcHBseShnZW5lcywgZnVuY3Rpb24oZ2VuZSkgewogIHAgPC0gVmxuUGxvdChSUE1fT3Jnc19BbGxvLAogICAgICAgICAgICAgICBmZWF0dXJlcyA9IGdlbmUsCiAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gImxlaWRlbl9zY1ZJXzEuMyIsCiAgICAgICAgICAgICAgIGNvbHMgPSBteV9jb2xvcnMsCiAgICAgICAgICAgICAgIGFscGhhID0gMC41KSArICAjIHNtYWxsZXIgZG90cwogICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gImtydXNrYWwudGVzdCIsIAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gInAuZm9ybWF0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwueCA9IDIsc2l6ZSA9IDUpICsKICAgIGdndGl0bGUoIiIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJpdGFsaWMiKSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAgIyBSZW1vdmUgbGVnZW5kCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArICAjIFJlbW92ZSB4LWF4aXMgbGFiZWwKICAgIGxhYnMoeSA9ICJFeHByZXNzaW9uIikgICMgQ2hhbmdlIHktYXhpcyBsYWJlbCB0byAiRXhwcmVzc2lvbiIKICByZXR1cm4ocCkKfSkKCiMgQXJyYW5nZSBwbG90cwpwYXRjaHdvcms6OndyYXBfcGxvdHMocGxvdHMsIG5jb2wgPSA2KQpgYGAKCgojIyMgVU1BUCBQbG90cyBieSBTYW1wbGUgYW5kIENsdXN0ZXIKIyMjIyAqKkV4dGVuZGVkIERhdGEgRmlnIDRhKioKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9NC41fQpEaW1QbG90KFJQTV9PcmdzLCBncm91cC5ieT0nR2Vub3R5cGUnLCBjb2xzPWMoImRhcmtvcmNoaWQ0Iiwib3JhbmdlIiksIHJlZHVjdGlvbj0ndW1hcCcsCiAgICAgICAgbGFiZWw9RkFMU0UsIGxhYmVsLnNpemU9Niwgc2h1ZmZsZT1UUlVFKSAmIE5vQXhlcygpCmBgYApgYGB7ciBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD00LjV9CgpEaW1QbG90KFJQTV9PcmdzLCBncm91cC5ieT0nY2x1c3RlcicsIGNvbHM9Y29sb3JzX2ZpZ0VENGEsIHJlZHVjdGlvbj0ndW1hcCcsCiAgICAgICAgbGFiZWw9VFJVRSwgbGFiZWwuc2l6ZT0xMCkgJiBOb0F4ZXMoKQoKYGBgCiMjIyMgKipFeHRlbmRlZCBEYXRhIEZpZyA0YyoqCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTQuNzV9CkRpbVBsb3QoUlBNX09yZ3MsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiUGhhc2UiLAogICAgICAgIHNodWZmbGU9VFJVRSwgbGFiZWw9RkFMU0UsIHB0LnNpemU9LjA1LCAKICAgICAgICBjb2xzPWMoImluZGlhbnJlZDMiLCJncmVlbjMiLCJyb3lhbGJsdWU0IikpICsgTm9BeGVzKCkKYGBgCgojIyMjIEV4dC4gRGF0YSBGaWcuIDRkIApgYGB7ciBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD01fQpEaW1QbG90KFJQTV9PcmdzX0FsbG8sIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiUGhhc2UiLAogICAgICAgIHNodWZmbGU9VFJVRSwgbGFiZWw9RkFMU0UsIHB0LnNpemU9LjA1LCAKICAgICAgICBjb2xzPWMoImluZGlhbnJlZDMiLCJncmVlbjMiLCJyb3lhbGJsdWU0IikpICsgTm9BeGVzKCkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD00fQojIFBsb3QgYmFycGxvdCBmb3IgRXh0LiBEYXRhIEZpZy4gNGQgIwojIyMjIyBXaGF0ICUgb2YgY2VsbHMgcGVyIHBoYXNlIGluIGVhY2ggZ3JvdXA/ICMjIyMKeCA8LSB0YWJsZShJZGVudHMoUlBNX09yZ3NfQWxsbyksUlBNX09yZ3NfQWxsb0BtZXRhLmRhdGEkUGhhc2UpCnByb3BvcnRpb25zIDwtIGFzLmRhdGEuZnJhbWUoMTAwKnByb3AudGFibGUoeCwgbWFyZ2luID0gMSkpCgpjb2xuYW1lcyhwcm9wb3J0aW9ucyk8LWMoIkNsdXN0ZXIiLCAiU2FtcGxlIiwgIkZyZXF1ZW5jeSIpCgojIGdnYmFycGxvdChwcm9wb3J0aW9ucywgeD0iU2FtcGxlIiwgeT0iRnJlcXVlbmN5IiwgZmlsbCA9ICJTYW1wbGUiLCBncm91cCA9ICJTYW1wbGUiLCB5bGFiID0gIkZyZXF1ZW5jeSAocGVyY2VudCkiLCB4bGFiPSJQaGFzZSIsIHBhbGV0dGUgPWMoImluZGlhbnJlZDMiLCJncmVlbjMiLCJyb3lhbGJsdWU0IikpKyB0aGVtZV9idygpKyBmYWNldF93cmFwKGZhY2V0cyA9ICJDbHVzdGVyIiwgc2NhbGVzPSJmcmVlX3kiLCBuY29sID00KSsgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpICtyb3RhdGVfeF90ZXh0KGFuZ2xlID0gNDUpCgojIFN0YWNrZWQKcDwtZ2dwbG90KHByb3BvcnRpb25zLCBhZXMoZmlsbD1TYW1wbGUsIHk9RnJlcXVlbmN5LCB4PUNsdXN0ZXIpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249InN0YWNrIiwgc3RhdD0iaWRlbnRpdHkiKQoKcCArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJpbmRpYW5yZWQzIiwiZ3JlZW4zIiwicm95YWxibHVlNCIpKSArIAogICAgdGhlbWVfYncoKSArIAogICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0yMCksIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTIwLGFuZ2xlPTQ1LCBoanVzdCA9IDEpLCAKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTIwKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MjApLCAKICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MjApLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0yMCkpICsKICAgIGxhYnMoeD1OVUxMLCB5PSJGcmVxdWVuY3kgKCUpIiwgZmlsbD1OVUxMKQoKYGBgCgoKCiMjIyMgRmlnIDFqCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTV9CkRpbVBsb3QoUlBNX0FsbG8sIGdyb3VwLmJ5PSdsZWlkZW5fc2NWSV8xLjMnLCBjb2xzPW15X2NvbG9ycywKICAgICAgICByZWR1Y3Rpb249J3VtYXAnLCBsYWJlbD1UUlVFLCBsYWJlbC5zaXplPTcpICYgTm9BeGVzKCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpgYGAKCiMjIyBVTUFQIGJ5IEZhdGUKIyMjIyAqKkZpZy4gMWsqKgpgYGB7ciBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQpwaGVub19jb2w8LWMoImJyb3duMiIsImRhcmtvcmNoaWQ0IiwiZG9kZ2VyYmx1ZSIsIiM2NkE2MUUiLCJvcmFuZ2UiLCJ0dXJxdW9pc2U0IikKCkRpbVBsb3QoUlBNX0FsbG8sIGdyb3VwLmJ5PWMoIlBoZW5vIiksIGNvbHM9cGhlbm9fY29sLCBzaHVmZmxlPVRSVUUsIHB0LnNpemU9MC42KStOb0F4ZXMoKQpgYGAKCiMjIyMgRmlnIDFsCmBgYHtyIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTUuNSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyBGaWcgMmcgcGxvdHMgIwpGZWF0dXJlUGxvdChSUE1fQWxsbywgZmVhdHVyZXMgPSBjKCJORV9zcGVhcm1hbiIpLCBwdC5zaXplPTAuMiwgCiAgICAgICAgICAgIHJlZHVjdGlvbj0ndW1hcCcsIG9yZGVyPVRSVUUpICsgCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzKG9wdGlvbj0icm9ja2V0IixkaXJlY3Rpb249LTEpICYgTm9BeGVzKCkKYGBgCgojIyMgVmlvbGluIHBsb3RzIG9mIEFyY2hldHlwZXMgYnkgbGVpZGVuIGNsdXN0ZXIKIyMjIyAqKkV4dC4gRGF0YSBGaWcuIDRmKioKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9ClZsblBsb3QoCiAgUlBNX0FsbG8sCiAgZmVhdHVyZXMgPSBjKCJBX0FyY2hldHlwZTEiLCJBMl9BcmNoZXR5cGUxIiwiTl9BcmNoZXR5cGUxIiwiUF9BcmNoZXR5cGUxIiksCiAgZ3JvdXAuYnkgPSAibGVpZGVuX3NjVklfMS4zIiwKICBjb2xzID0gbXlfY29sb3JzLAogIGFscGhhID0gMC43LAogIG5jb2wgPSAyCikgJiAKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwgICAgICAgICAgICAgICAgIyBzbWFsbGVyIHgtYXhpcyBsYWJlbHMKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZT0wKSwgICAgICAgICAgIyBpdGFsaWNpemUgdGl0bGVzCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI0KSwgICAgICAgICAgICAgICMgb3B0aW9uYWwgc2l6ZSB0d2Vha3MKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjQpCiAgKSAmCiAgbGFicygKICAgIHkgPSAiRXhwcmVzc2lvbiIsCiAgICB4ID0gIkNsdXN0ZXIiCiAgKQoKYGBgCgoKIyMjIFBsb3QgU2lnbmF0dXJlIFNjb3JlcyBieSBQaGVub3R5cGUKYGBge3J9CnBoZW5vdHlwZXMgPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShSUE1fQWxsbyRQaGVubykpCnBoZW5vX3BhaXJzX2xpc3QgPC0gY29tYm4ocGhlbm90eXBlcywgMiwgc2ltcGxpZnkgPSBGQUxTRSkKYGBgCgojIyMjIERlZmluZSBmdW5jdGlvbiB0byBwbG90IHZpb2xpbiBwbG90cyBieSBwaGVub3R5cGUKYGBge3J9CnBsb3RWbG5CeVBoZW4gPC0gZnVuY3Rpb24oZmVhdHVyZSwgeWw9YygtMC4xLDAuMyksIGZvY3VzPU5BKSB7CiAgICBpZighaXMubmEoZm9jdXMpKSB7CiAgICAgICAgcGhlbm9fcGFpcnNfbGlzdCA8LSBwaGVub19wYWlyc19saXN0W3NhcHBseShwaGVub19wYWlyc19saXN0LCBmdW5jdGlvbih4KSBmb2N1cyAlaW4lIHgpXQogICAgfQogICAgCiAgICBzY2F0ZXI6OnBsb3RDb2xEYXRhKHNjZSwgeCA9ICJQaGVubyIsIHkgPSBmZWF0dXJlLCBjb2xvdXJfYnkgPSAiUGhlbm8iKSArIAogICAgICAgIHNjYWxlX2Rpc2NyZXRlX21hbnVhbChhZXN0aGV0aWNzID0gYygiY29sb3VyIiwgImZpbGwiKSwgdmFsdWVzPXBoZW5vX2NvbCkgKwogICAgICAgIHRoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjQpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCAgICMgcm90YXRlIHgtYXhpcyBsYWJlbHMKICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAgICAjIHJlbW92ZSBwbG90IHRpdGxlCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiICAgICAgICAgIyByZW1vdmUgbGVnZW5kCiAgICAgICAgKSArIGxhYnMoeCA9ICIiLCAgICAgICAgICAgICAgICAgICAgICMgY3VzdG9tIHgtYXhpcyB0aXRsZQogICAgICAgICAgICAgICAgIHkgPSAiU2lnbmF0dXJlIHNjb3JlIiAgICAgICAgIyBjdXN0b20geS1heGlzIHRpdGxlCiAgICAgICAgKSArIHlsaW0oeWxbMV0sIHlsWzJdKSArIAogICAgICAgIGdlb21fYm94cGxvdChmaWxsPXBoZW5vX2NvbCwgYWxwaGE9MS81LCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gLjIpLAogICAgICAgICAgICAgICAgICAgICBzaXplPTAuMiwgY29sb3I9ImJsYWNrIiwgbm90Y2g9VFJVRSwgbm90Y2h3aWR0aD0wLjMsIG91dGxpZXIuc2hhcGUgPSAyLCBvdXRsaWVyLmNvbG91cj1OQSkgIyAgICsgCiAgICAgICAgIyBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwKICAgICAgICAjICAgICAgICAgICAgICBnZW9tID0gInBvaW50IiwKICAgICAgICAjICAgICAgICAgICAgICBzaGFwZSA9IDE4LAogICAgICAgICMgICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICMgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsCiAgICAgICAgIyAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNSkpICsgCiAgICAgICAgIyBnZ3B1YnI6OnN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAid2lsY294LnRlc3QiLCBsYWJlbCA9ICJwLnNpZ25pZiIsIHNpemU9NCwgCiAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDAuNSwKICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGUubnMgPSBUUlVFLCBjb21wYXJpc29ucyA9IHBoZW5vX3BhaXJzX2xpc3QpCn0KYGBgCgoKIyMjIyBGaWcgMWwKTkUgY29ycmVsYXRpb24KYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9Mi41LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90VmxuQnlQaGVuKCJORV9zcGVhcm1hbiIsIHlsPWMoLS43NSwgLjgpLCBmb2N1cz0iTkUiKQpgYGAKCiMjIyMgRmlnIDFtClNDTEMgY2VsbCB0eXBlIGNvbnNlbnN1cyBzaWduYXR1cmUgc2NvcmVzCiogTkUgY2VsbAoqIFR1ZnQgY2VsbAoqIEJhc2FsIGNlbGwKYGBge3IgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGxvdFZsbkJ5UGhlbigiTkVfQ29uc2Vuc3VzMSIsIHlsPWMoLTAuNSwgMSkpCnBsb3RWbG5CeVBoZW4oIlR1ZnRfQ29uc2Vuc3VzMSIsIHlsPWMoLTAuMSwgMC41KSkKcGxvdFZsbkJ5UGhlbigiQmFzYWxfQ29uc2Vuc3VzMSIsIHlsPWMoLTAuMSwgMS4xKSkKYGBgCiMjIyMgRmlnIDFuClRGIHRhcmdldCBnZW5lIHNjb3JlcwoqIEFTQ0wxIHRhcmdldHMKKiBORVVST0QxIHRhcmdldHMKKiBBVE9IMSB0YXJnZXRzCiogUE9VMkYzIHRhcmdldHMKKiBZQVAxIGFjdGl2aXR5IHNjb3JlCgpgYGB7ciBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD0zLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwbG90VmxuQnlQaGVuKCJBU0NMMV9UYXJnZXRzMSIsIHlsPWMoLTAuMSwwLjYpKQpwbG90VmxuQnlQaGVuKCJORVVST0QxX1RhcmdldHMxIiwgeWw9YygtMC4xLDAuMjUpKQpwbG90VmxuQnlQaGVuKCJBVE9IMV9UYXJnZXRzMSIsIHlsPWMoLTAuMSwuMykpCnBsb3RWbG5CeVBoZW4oIlBPVTJGM19UYXJnZXRzMSIsIHlsPWMoLTAuMSwgMC4yMikpCnBsb3RWbG5CeVBoZW4oIllBUDFfQWN0aXZpdHlfU2NvcmUxIiwgeWw9YygtMC4xLCAxKSkKYGBgCgo=